summaryrefslogtreecommitdiffstats
path: root/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractListAdapter.kt
blob: 3dfee3d0c58932a2754a7a2f137a65f0538f8f8d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

package org.yuzu.yuzu_emu.adapters

import android.annotation.SuppressLint
import androidx.recyclerview.widget.RecyclerView
import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder

/**
 * Generic list class meant to take care of basic lists
 * @param currentList The list to show initially
 */
abstract class AbstractListAdapter<Model : Any, Holder : AbstractViewHolder<Model>>(
    open var currentList: List<Model>
) : RecyclerView.Adapter<Holder>() {
    override fun onBindViewHolder(holder: Holder, position: Int) =
        holder.bind(currentList[position])

    override fun getItemCount(): Int = currentList.size

    /**
     * Adds an item to [currentList] and notifies the underlying adapter of the change. If no parameter
     * is passed in for position, [item] is added to the end of the list. Invokes [callback] last.
     * @param item The item to add to the list
     * @param position Index where [item] will be added
     * @param callback Lambda that's called at the end of the list changes and has the added list
     * position passed in as a parameter
     */
    open fun addItem(item: Model, position: Int = -1, callback: ((position: Int) -> Unit)? = null) {
        val newList = currentList.toMutableList()
        val positionToUpdate: Int
        if (position == -1) {
            newList.add(item)
            currentList = newList
            positionToUpdate = currentList.size - 1
        } else {
            newList.add(position, item)
            currentList = newList
            positionToUpdate = position
        }
        onItemAdded(positionToUpdate, callback)
    }

    protected fun onItemAdded(position: Int, callback: ((Int) -> Unit)? = null) {
        notifyItemInserted(position)
        callback?.invoke(position)
    }

    /**
     * Replaces the [item] at [position] in the [currentList] and notifies the underlying adapter
     * of the change. Invokes [callback] last.
     * @param item New list item
     * @param position Index where [item] will replace the existing list item
     * @param callback Lambda that's called at the end of the list changes and has the changed list
     * position passed in as a parameter
     */
    fun changeItem(item: Model, position: Int, callback: ((position: Int) -> Unit)? = null) {
        val newList = currentList.toMutableList()
        newList[position] = item
        currentList = newList
        onItemChanged(position, callback)
    }

    protected fun onItemChanged(position: Int, callback: ((Int) -> Unit)? = null) {
        notifyItemChanged(position)
        callback?.invoke(position)
    }

    /**
     * Removes the list item at [position] in [currentList] and notifies the underlying adapter
     * of the change. Invokes [callback] last.
     * @param position Index where the list item will be removed
     * @param callback Lambda that's called at the end of the list changes and has the removed list
     * position passed in as a parameter
     */
    fun removeItem(position: Int, callback: ((position: Int) -> Unit)? = null) {
        val newList = currentList.toMutableList()
        newList.removeAt(position)
        currentList = newList
        onItemRemoved(position, callback)
    }

    protected fun onItemRemoved(position: Int, callback: ((Int) -> Unit)? = null) {
        notifyItemRemoved(position)
        callback?.invoke(position)
    }

    /**
     * Replaces [currentList] with [newList] and notifies the underlying adapter of the change.
     * @param newList The new list to replace [currentList]
     */
    @SuppressLint("NotifyDataSetChanged")
    open fun replaceList(newList: List<Model>) {
        currentList = newList
        notifyDataSetChanged()
    }
}